package me.helllp.bootman.back.config;

import java.lang.reflect.Method;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import redis.clients.jedis.JedisPoolConfig;

/**
 * Redis的配置
 * 
 * @author 虎头
 *
 */
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
	@Value("${bootman.redis.database}")
	private int database;
	
	@Value("${bootman.redis.host}")
	private String hostName;
	
	@Value("${bootman.redis.port}")
	private int port;
	
	@Value("${bootman.redis.timeout}")
	private int timeout;
	
	@Value("${bootman.redis.password}")
	private String password;
	
	/**
	 * 最大连接数
	 */
	@Value("${bootman.redis.pool.max-active}")
	private int maxActive;
	
	/**
	 * 最大空闲等待数
	 */
	@Value("${bootman.redis.pool.max-idle}")
	private int maxIdle;
	
	/**
	 * 初始化连接数
	 */
	@Value("${bootman.redis.pool.min-idle}")
	private int minIdle;
	
	/**
	 * 最大等待时间
	 */
	@Value("${bootman.redis.pool.max-wait}")
	private int maxWait;
	
	/**
	 * 自定义key的规则
	 */
	@Bean
	public KeyGenerator keyGenerator() {
		return new KeyGenerator() {
			@Override
			public Object generate(Object target, Method method, Object... params) {
                StringBuilder sb = new StringBuilder();  
                sb.append(target.getClass().getName());  
                sb.append(":");
                sb.append(method.getName());  
                for (Object o : params) {  
                    sb.append(":").append(o.toString());  
                }  
                return sb.toString();
			}
		};
	}

	@SuppressWarnings("rawtypes")
	@Bean
	public CacheManager cacheManager(RedisTemplate redisTemplate) {
		return new RedisCacheManager(redisTemplate);
	}

	/**
	 * 构造Redis连接池配置
	 * 
	 * @return
	 */
	public JedisPoolConfig redisConfig(){
		JedisPoolConfig config = new JedisPoolConfig();
		config.setMaxTotal(maxActive);
		config.setMaxIdle(maxIdle);
		config.setMaxWaitMillis(maxWait);
		config.setMinIdle(minIdle);
		
		return config;
	}
	
	@Bean
	public JedisConnectionFactory getConnectionFactory(){
		JedisConnectionFactory factory = new JedisConnectionFactory();
		factory.setDatabase(database);
		factory.setHostName(hostName);
		factory.setPassword(password);
		factory.setPoolConfig(redisConfig());
		factory.setPort(port);
		factory.setTimeout(timeout);

		return factory;
	}
	
	/**
	 * 监听Redis的事件
	 * 
	 * @param factory
	 * @return
	 */
	@Bean
	public RedisMessageListenerContainer redisContainer(JedisConnectionFactory factory){
		RedisMessageListenerContainer container = new RedisMessageListenerContainer();
		container.setConnectionFactory(factory);
		return container;
	}
	
	@Bean
	public RedisTemplate<String, Object> redisTemplate(JedisConnectionFactory factory) {
        GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        
		RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
		
		//	定义对象的序列化方法
		template.setConnectionFactory(factory);
		template.setKeySerializer(new StringRedisSerializer());
		template.setValueSerializer(jsonRedisSerializer);
		template.setHashKeySerializer(jsonRedisSerializer);
		template.setHashValueSerializer(jsonRedisSerializer);
//		template.setStringSerializer(new StringRedisSerializer());
		template.afterPropertiesSet();
        
        return template;
	}
	

}
